/**
 * File: ReadMapper.java
 * Created by: mhaimel
 * Created on: Mar 9, 2010
 * CVS:  $Id: ReadMapper.java 1.0 Mar 9, 2010 1:44:51 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.model.graph.curtain;

import static uk.ac.ebi.curtain.utils.ArrayHelper.castArray;

import org.apache.commons.lang.StringUtils;

import uk.ac.ebi.curtain.model.graph.Graph;
import uk.ac.ebi.curtain.model.graph.io.ReadMapper;
import uk.ac.ebi.curtain.model.graph.io.WriteMapper;

/**
 * @author mhaimel
 *
 */
public class ReadSequMapper implements WriteMapper<ReadInfo>, ReadMapper<ReadInfo> {

	private static final char SEP_CHAR = ';';
	private static final char SUB_SEP_CHAR = ',';
	private static final String[] header = new String[]{
		"read_categories","multiplicity","weight_sum","gap_size"};
	
	@Override
	public String[] getHeader() {
		return header;
	}

	@Override
	public Object[] toArray(ReadInfo value) {
		return new Object[]{
				value.getCategories(),
				joinArray(value.arrayOfMultiplicity()),
				joinArray(value.arrayOfWeightSum()),
				joinArrayArray(value.arrayOfGaps())
		};
	}

	@Override
	public int getFieldCount() {
		return header.length;
	}

	@Override
	public ReadInfo loadValue(String[] array, int i, Graph graph) {
		Integer cat = Integer.valueOf(array[i++]);
		Integer[] mult = splitString(array[i++], Integer.class, cat);
		Double[] weight = splitString(array[i++], Double.class, cat);
		Integer[][] gaps = splitGaps(array[i++],Integer.class,cat);
		ReadInfo read = new ReadInfo(cat,mult,weight,gaps);
		return read;
	}
	
	private Integer[][] splitGaps(String val, Class<Integer> clazz,Integer cat) {
		Integer[][] res = new Integer[cat][];
		String[] split = splitString(val, cat);
		for(int i = 0; i < cat; ++i){
			Integer[] arr = 
				castArray(
					StringUtils.split(split[i], SUB_SEP_CHAR),
					Integer.class);
			res[i] = arr;
		}
		return res;
	}

	private <T extends Number> T[] splitString(String val, Class<T> clazz, Integer cat){
		String[] split = splitString(val, cat);
		T[] arr = castArray(split, clazz);
		return arr;
	}
	
	private String[] splitString(String val, Integer expectedSize){
		String[] arr = StringUtils.splitPreserveAllTokens(val, SEP_CHAR);
		int len = arr.length;
		if(!expectedSize.equals(len)){
			throw new IllegalStateException("Expected " + expectedSize + " categories, but " + len + " found in: " + val);
		}	
		return arr;
	}
	
	private String joinArray(Object[] arr){
		return StringUtils.join(arr, SEP_CHAR);
	}
	
	private String joinArrayArray(Object[][] arr){
		int len = arr.length;
		String[] tmpArr = new String[len];
		for(int i = 0; i < len; i++){
			tmpArr[i] = StringUtils.join(arr[i], SUB_SEP_CHAR);
		}
		return StringUtils.join(tmpArr, SEP_CHAR);
	}
	
}
